package com.movie.service;

import com.movie.dto.UserDTO;
import com.movie.dto.VipLevelDTO;
import com.movie.entity.User;
import com.movie.entity.VipLevel;
import com.movie.repository.UserRepository;
import com.movie.repository.VipLevelRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final VipLevelRepository vipLevelRepository;
    private final PasswordEncoder passwordEncoder;

    public List<UserDTO> findAll() {
        return userRepository.findAll()
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public Page<UserDTO> findAll(Pageable pageable) {
        return userRepository.findAll(pageable)
                .map(this::convertToDTO);
    }

    public Page<UserDTO> findByKeyword(String keyword, Pageable pageable) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return userRepository.findAll(pageable)
                    .map(this::convertToDTO);
        }

        // 使用自定义查询进行分页搜索
        return userRepository.findByUsernameOrEmailContaining(keyword, pageable)
                .map(this::convertToDTO);
    }

    public UserDTO findById(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }

    @Transactional
    public UserDTO create(UserDTO userDTO) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(userDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(userDTO.getEmail())) {
            throw new RuntimeException("邮箱已存在");
        }

        User user = convertToEntity(userDTO);
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));

        // 设置VIP等级
        if (userDTO.getVipLevel() != null && userDTO.getVipLevel().getId() != null) {
            VipLevel vipLevel = vipLevelRepository.findById(userDTO.getVipLevel().getId())
                    .orElseThrow(() -> new RuntimeException("VIP等级不存在"));
            user.setVipLevel(vipLevel);
        }

        User saved = userRepository.save(user);
        return convertToDTO(saved);
    }

    @Transactional
    public UserDTO update(Long id, UserDTO userDTO) {
        User existing = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 检查用户名是否被其他用户使用
        if (!existing.getUsername().equals(userDTO.getUsername()) &&
                userRepository.existsByUsername(userDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查邮箱是否被其他用户使用
        if (!existing.getEmail().equals(userDTO.getEmail()) &&
                userRepository.existsByEmail(userDTO.getEmail())) {
            throw new RuntimeException("邮箱已存在");
        }

        BeanUtils.copyProperties(userDTO, existing, "id", "password", "createdAt", "updatedAt", "vipLevel");

        // 如果提供了新密码，则加密更新
        if (userDTO.getPassword() != null && !userDTO.getPassword().isEmpty()) {
            existing.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        }

        // 处理VIP等级更新
        if (userDTO.getVipLevel() != null && userDTO.getVipLevel().getId() != null) {
            VipLevel vipLevel = vipLevelRepository.findById(userDTO.getVipLevel().getId())
                    .orElseThrow(() -> new RuntimeException("VIP等级不存在"));
            existing.setVipLevel(vipLevel);
        } else {
            // 如果VIP等级为null，清除VIP等级关联
            existing.setVipLevel(null);
        }

        User updated = userRepository.save(existing);
        return convertToDTO(updated);
    }

    @Transactional
    public void delete(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        userRepository.delete(user);
    }

    @Transactional
    public UserDTO toggleStatus(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        user.setStatus(!user.getStatus());
        User updated = userRepository.save(user);
        return convertToDTO(updated);
    }

    @Transactional
    public void updateLastLogin(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        user.setLastLogin(LocalDateTime.now());
        userRepository.save(user);
    }

    public List<UserDTO> findByRole(String roleName) {
        // 由于User实体已改为多角色，此方法需要重新实现
        // 暂时返回空列表，需要根据具体业务需求实现
        return List.of();
    }

    public List<UserDTO> findByStatus(Boolean status) {
        return userRepository.findByStatus(status)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public UserDTO findByUsername(String username) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }

    public UserDTO findByEmail(String email) {
        User user = userRepository.findByEmail(email)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }

    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(user, dto);
        // 设置VIP等级对象
        if (user.getVipLevel() != null) {
            dto.setVipLevel(convertVipLevelToDTO(user.getVipLevel()));
        }
        return dto;
    }

    private User convertToEntity(UserDTO dto) {
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        // VIP等级对象需要特殊处理，因为BeanUtils无法直接复制关联对象
        // VIP等级会在业务逻辑中单独设置
        return user;
    }

    private VipLevelDTO convertVipLevelToDTO(VipLevel vipLevel) {
        VipLevelDTO dto = new VipLevelDTO();
        BeanUtils.copyProperties(vipLevel, dto);
        return dto;
    }
}